import { Injectable } from '@angular/core';
import { Observable, Subject } from 'rxjs';
import { filter, map } from 'rxjs/operators';
import { webSocket, WebSocketSubject } from 'rxjs/webSocket';

import { MessageBody, MessageReceiveData, Receive, Send } from './interface';
import { SendArgumentsType } from './message-ts-util';

@Injectable({
  providedIn: 'root'
})
export class MessageService {
  private ws!: WebSocketSubject<MessageBody<Receive | Send>> | null;
  private received$ = new Subject<MessageBody<Receive>>();

  constructor() {}

  connect(): void {
    this.ws = webSocket({
      url: 'ws://8.135.95.248:20101/websocket/property'
    });
    this.ws.subscribe(data => this.received$.next(data as MessageBody<Receive>));
  }

  receive<K extends Receive>(action: K): Observable<MessageReceiveData[K]> {
    return this.received$.pipe(
      filter(message => message.action === action),
      map(message => {
        if (message && message.data) {
          return message.data;
        } else {
          return { message: 'no data' };
        }
      })
    ) as Observable<MessageReceiveData[K]>;
  }

  send<K extends Send>(...args: SendArgumentsType<K>): void {
    const [action, data] = args;
    this.ws?.next({
      action,
      data
    });
  }
}
